﻿using ApiConceptsFramework.HCs;
using FluentAssertions;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;

namespace test.ApiConceptsFramework.HCs
{
	[TestFixture]
	public class XmlTests
	{
		[Test]
		public void Returns_null_when_input_data_is_null()
		{
			new Xml().Evaluate(null, null, null, null).Should().BeNull();
		}

		[Test]
		public void Cost_of_1_element_with_2_attributes_is_correctly_calculated()
		{
			//Arrange
			var xmlPattern = new Xml();
			var patternData = new XmlInputData
				{
					SchemaAvailable = true,
					Elements = new List<XmlElement>{new XmlElement
						{
							Name = "test",
							NumberOfUsages = 1, 
							PreviousUsages = 0,
							Attributes = new List<XmlAttribute>{ new XmlAttribute{Name = "a1", NumberOfUsages = 1, PreviousUsages = 0}, new XmlAttribute{Name = "a2", NumberOfUsages = 1, PreviousUsages = 0}}
						}}
				};
			const float expectedSearchComplexity = Xml.ElementSearchComplexity + Xml.AttributeSearchComplexity*2;
			const float expectedUsageComplexity = Xml.ElementUsageComplexity + Xml.AttributeUsageComplexity*2;

			//Act
			var result = xmlPattern.Evaluate(null, null, patternData, null);

			//Assert
			result.ComplexityData.Should().HaveCount(1);
			result.GeneralComplexity.Should().Be(Xml.XmlBaseComplexity);
			result.GeneralSuggestions.Should().HaveCount(1);
			result.ComplexityData[0].SearchComplexity.Should().Be(expectedSearchComplexity);
			result.ComplexityData[0].UsageComplexity.Should().Be(expectedUsageComplexity);
			result.ComplexityData[0].Suggestions.Should().BeNull();
		}

		[Test]
		public void Cost_increases_when_no_schema_is_available()
		{
			//Arrange
			var xmlPattern = new Xml();
			var patternData = new XmlInputData
			{
				SchemaAvailable = false,
				Elements = new List<XmlElement>{new XmlElement
						{
							Name = "test",
							NumberOfUsages = 1, 
							PreviousUsages = 0,
							Attributes = new List<XmlAttribute>{ new XmlAttribute{Name = "a1", NumberOfUsages = 1, PreviousUsages = 0}, new XmlAttribute{Name = "a2", NumberOfUsages = 1, PreviousUsages = 0}}
						}}
			};
			const float expectedSearchComplexity =
				Xml.ElementSearchComplexity*Xml.NoSchemaSearchMultiplicator +
				(Xml.AttributeSearchComplexity*Xml.NoSchemaSearchMultiplicator)*2;
			const float expectedUsageComplexity = Xml.ElementUsageComplexity*Xml.NoSchemaUsageMultiplicator +
			                                      (Xml.AttributeUsageComplexity*Xml.NoSchemaUsageMultiplicator)*2;

			//Act
			var result = xmlPattern.Evaluate(null, null, patternData, null);

			//Assert
			result.GeneralSuggestions.Should().HaveCount(2);
			result.ComplexityData.Should().HaveCount(1);
			result.ComplexityData[0].SearchComplexity.Should().Be(expectedSearchComplexity);
			result.ComplexityData[0].UsageComplexity.Should().Be(expectedUsageComplexity);
			
		}

		[Test]
		public void Cost_increases_for_long_names()
		{
			//Arrange
			var xmlPattern = new Xml();
			var patternData = new XmlInputData
			{
				SchemaAvailable = false,
				Elements = new List<XmlElement>{new XmlElement
						{
							Name = "longelementname",
							NumberOfUsages = 1, 
							PreviousUsages = 0,
							Attributes = new List<XmlAttribute>{ new XmlAttribute{Name = "longattributename", NumberOfUsages = 1, PreviousUsages = 0}}
						}}
			};
			const float expectedSearchComplexity = Xml.ElementSearchComplexity*Xml.NoSchemaSearchMultiplicator +
			                                       Xml.AttributeSearchComplexity*Xml.NoSchemaSearchMultiplicator;
			const float expectedUsageComplexity = Xml.ElementUsageComplexity*Xml.NoSchemaUsageMultiplicator +
			                                      Xml.AttributeUsageComplexity*Xml.NoSchemaUsageMultiplicator; //+
			                                 //Xml.AdditionalComplexityOfLongName*2;

			//Act
			var result = xmlPattern.Evaluate(null, null, patternData, null);

			//Assert
			result.ComplexityData.Should().HaveCount(1);
			result.ComplexityData[0].SearchComplexity.Should().Be(expectedSearchComplexity);
			result.ComplexityData[0].UsageComplexity.Should().Be(expectedUsageComplexity);
			result.ComplexityData[0].Suggestions.Should().HaveCount(2);
		}
	}
}
